home *** CD-ROM | disk | FTP | other *** search
- /*
-
- RTP packet encoding and decoding routines
-
- */
-
- #include "netfone.h"
-
- #ifdef RTP_SUPPORT
- typedef enum {
- AE_PCMU, AE_PCMA, AE_G721, AE_IDVI, AE_G723, AE_GSM,
- AE_1016, AE_LPC,
- AE_L8, AE_L16, AE_L24, AE_L32,
- AE_G728, AE_TRUE,
- AE_MAX
- } audio_encoding_t;
-
- /* common audio description for files and workstation */
- typedef struct {
- audio_encoding_t encoding; /* type of encoding (differs) */
- unsigned sample_rate; /* sample frames per second */
- unsigned channels; /* number of interleaved channels */
- } audio_descr_t;
- #endif
-
- #define bcopy(s, d, l) _fmemcpy(d, s, l)
-
- /* RTP_MAKE_SDES -- Generate a source description for this
- user, based either on information obtained
- from the password file or supplied by
- environment variables. */
-
- int rtp_make_sdes(char **pkt, unsigned long ssrc_i, int exact)
- {
- char p[512];
- rtcp_t *rp = (rtcp_t *) p;
- char *ap;
- int l;
- char s[256];
-
- #define addSDES(item, text) *ap++ = item; *ap++ = l = strlen(text); \
- bcopy(text, ap, l); ap += l
-
- #ifdef REASONABLE
- rp->common.version = RTP_VERSION;
- rp->common.p = 0;
- rp->common.count = 1;
- rp->common.pt = RTCP_SDES;
- #else
- *((short *) p) = (RTP_VERSION << 14) | RTCP_SDES | (1 << 8);
- #endif
- rp->r.sdes.src = ssrc_i;
-
- ap = (char *) rp->r.sdes.item;
-
- /* Build canonical name for this user. This is generally
- a name which can be used for "talk" and "finger", and
- is not necessarily the user's E-mail address. If the
- exact flag is set, we precede the name with an asterisk
- to inform the LWL server this name cannot be matched by
- a wild card. */
-
- if (exact) {
- s[0] = '*';
- strcpy(s + 1, lwl_s_email);
- addSDES(RTCP_SDES_CNAME, s);
- } else {
- addSDES(RTCP_SDES_CNAME, lwl_s_email);
- }
- if (lwl_s_fullname[0]) {
- addSDES(RTCP_SDES_NAME, lwl_s_fullname);
- }
- addSDES(RTCP_SDES_EMAIL, lwl_s_email);
- if (lwl_s_phone[0]) {
- addSDES(RTCP_SDES_PHONE, lwl_s_phone);
- }
- if (lwl_s_location[0]) {
- addSDES(RTCP_SDES_LOC, lwl_s_location);
- }
-
- addSDES(RTCP_SDES_TOOL, rstring(IDS_T_RTP_TOOL));
-
- /* Add a PRIV item indicating the port we're communicating on. */
-
- sprintf(s, Format(59), NETFONE_COMMAND_PORT);
- addSDES(RTCP_SDES_PRIV, s);
-
- *ap++ = RTCP_SDES_END;
- *ap++ = 0;
-
- l = ap - p;
-
- rp->common.length = ((l + 3) / 4) - 1;
- l = (rp->common.length + 1) * 4;
- *pkt = (char *) malloc(l);
- if (*pkt == NULL) {
- return 0;
- }
- revshort((short *) p);
- revshort((short *) (p + 2));
- bcopy(p, *pkt, l);
- return l;
- }
-
- /* RTP_MAKE_BYE -- Create a "BYE" RTCP packet for this connection. */
-
- int rtp_make_bye(char *p, unsigned long ssrc_i, char *raison)
- {
- rtcp_t *rp = (rtcp_t *) p;
- char *ap;
- int l;
-
- #ifdef REASONABLE
- rp->common.version = RTP_VERSION;
- rp->common.p = 0;
- rp->common.count = 1;
- rp->common.pt = RTCP_BYE;
- #else
- *((short *) p) = (RTP_VERSION << 14) | RTCP_BYE | (1 << 8);
- #endif
- rp->r.bye.src[0] = ssrc_i;
-
- ap = (char *) rp->r.sdes.item;
-
- l = 0;
- if (raison != NULL) {
- l = strlen(raison);
- if (l > 0) {
- *ap++ = l;
- bcopy(raison, ap, l);
- ap += l;
- }
- }
-
- while ((ap - p) & 3) {
- *ap++ = 0;
- }
- l = ap - p;
-
- rp->common.length = (l / 4) - 1;
- l = (rp->common.length + 1) * 4;
- revshort((short *) p);
- revshort((short *) (p + 2));
- return l;
- }
-
- #ifdef RTP_SUPPORT
-
- /* RTPOUT -- Convert a sound buffer into an RTP packet, given the
- SSRC, timestamp, and sequence number appropriate for the
- next packet sent to this connection. */
-
- LONG rtpout(soundbuf *sb, unsigned long ssrc_i,
- unsigned long timestamp_i, unsigned short seq_i)
- {
- soundbuf rp;
- rtp_hdr_t *rh = (rtp_hdr_t *) &rp;
- LONG pl = 0;
-
- rh->version = RTP_VERSION;
- rh->p = 0;
- rh->x = 0;
- rh->cc = 0;
- rh->m = 0;
- rh->seq = seq_i;
- rh->ts = timestamp_i;
- rh->ssrc = ssrc_i;
-
- if (sb->compression & fCompGSM) {
- rh->pt = 3;
- bcopy(sb->buffer.buffer_val + 2, ((char *) &rp) + 12,
- (int) sb->buffer.buffer_len - 2);
- pl = (sb->buffer.buffer_len - 2) + 12;
-
- } else if (sb->compression & fCompADPCM) {
- rh->pt = 5;
- bcopy(sb->buffer.buffer_val, ((char *) &rp) + 12 + 4,
- (int) sb->buffer.buffer_len - 3);
- bcopy(sb->buffer.buffer_val + ((int) sb->buffer.buffer_len - 3),
- ((char *) &rp) + 12, 3);
- ((char *) &rp)[15] = 0;
- pl = (sb->buffer.buffer_len - 1) + 12;
-
- } else { /* Uncompressed PCMU samples */
- rh->pt = 0;
- bcopy(sb->buffer.buffer_val, ((char *) &rp) + 12,
- (int) sb->buffer.buffer_len);
- pl = (int) sb->buffer.buffer_len + 12;
- }
- if (pl > 0) {
- bcopy((char *) &rp, (char *) sb, (int) pl);
- }
- return pl;
- }
-
- audio_descr_t adt[] = {
- /* enc sample ch */
- {AE_PCMU, 8000, 1}, /* 0 PCMU */
- {AE_MAX, 8000, 1}, /* 1 1016 */
- {AE_G721, 8000, 1}, /* 2 G721 */
- {AE_GSM, 8000, 1}, /* 3 GSM */
- {AE_G723, 8000, 1}, /* 4 Unassigned */
- {AE_IDVI, 8000, 1}, /* 5 DVI4 */
- {AE_IDVI, 16000, 1}, /* 6 DVI4 */
- {AE_LPC, 8000, 1}, /* 7 LPC */
- {AE_MAX, 0, 1}, /* 8 PCMA */
- {AE_MAX, 0, 1}, /* 9 G722 */
- {AE_L16, 44100, 2}, /* 10 L16 */
- {AE_L16, 44100, 1}, /* 11 L16 */
- {AE_MAX, 0, 1}, /* 12 */
- };
-
- #define MAX_MISORDER 100
- #define MAX_DROPOUT 3000
-
- int isrtp(unsigned char *pkt, int len, struct connection *c)
- {
- rtp_hdr_t *rh = (rtp_hdr_t *) pkt;
-
- /*fprintf(stderr, "Ver = %d, pt = %d, p = %d, x = %d\n",
- rh->version, rh->pt, rh->p, rh->x); */
-
- if (rh->version == RTP_VERSION && /* Version ID correct */
- rh->pt < ELEMENTS(adt) && /* Payload type credible */
- adt[rh->pt].sample_rate != 0 && /* Defined payload type */
- /* Padding, if present, is plausible */
- (!rh->p || (pkt[len - 1] < (len - (12 + 4 * rh->cc)))) &&
- !rh->x /* No extension present */
- ) {
- struct soundbuf sb;
- unsigned char *payload;
- int paylen;
-
- payload = pkt + (12 + 4 * rh->cc); /* Start of payload */
- paylen = len - ((12 + 4 * rh->cc) +/* Length of payload */
- (rh->p ? pkt[len - 1] : 0));
- sb.compression = 0;
- sb.buffer.buffer_len = 0;
-
- /* Fake an RTP unique host name from the SSRC identifier. */
-
- sprintf(sb.sendinghost, Format(60),
- pkt[8], pkt[9], pkt[10], pkt[11]);
-
- switch (adt[rh->pt].encoding) {
-
- case AE_PCMU:
- sb.buffer.buffer_len = paylen;
- bcopy(payload, sb.buffer.buffer_val, paylen);
- break;
-
- case AE_GSM:
- sb.buffer.buffer_len = paylen + sizeof(short);
- bcopy(payload, sb.buffer.buffer_val + 2, paylen);
- *((short *) sb.buffer.buffer_val) =
- (paylen * 160) / 33;
- sb.compression |= fCompGSM;
- break;
-
- case AE_IDVI:
- bcopy(payload + 4, sb.buffer.buffer_val, paylen - 4);
- sb.buffer.buffer_len = paylen - 1;
- bcopy(payload, sb.buffer.buffer_val + (paylen - 4), 3);
- sb.buffer.buffer_len = paylen - 1;
- if (adt[rh->pt].sample_rate == 8000) {
- sb.compression |= fCompADPCM;
- } else {
-
- /* Bogus attempt to convert sampling rate. We
- really need to do this in linear mode, which isn't
- supported on all SPARCs. This is better than
- nothing, though. */
-
- int inc = adt[rh->pt].sample_rate / 8000, i;
- unsigned char *in = (unsigned char *) sb.buffer.buffer_val,
- *out = (unsigned char *) sb.buffer.buffer_val;
-
- adpcmdecomp(&sb);
- for (i = 0; i < (paylen - 4) / inc; i++) {
- *out++ = *in;
- in += inc;
- }
- sb.buffer.buffer_len /= inc;
- }
- break;
-
- #ifdef LPC_IMPLEMENTED
- case AE_LPC:
- {
- lpc_synthesize((lpcparams_t *) payload, 1.0,
- (unsigned char *) sb.buffer.buffer_val);
- sb.buffer.buffer_len = 160;
- }
- break;
- #endif
-
- case AE_L16:
- if (adt[rh->pt].channels == 1) {
- int i, j, k;
-
- for (i = j = k = 0; i < (paylen / 8); i++) {
- if ((k & 3) != 2 && ((i % 580) != 579)) {
- sb.buffer.buffer_val[j++] =
- audio_s2u((((unsigned short *) payload)[i * 4]));
- }
- k = (k + 1) % 11;
- }
- sb.buffer.buffer_len = j;
- } else if (adt[rh->pt].channels == 2) {
- int i, j, k;
-
- for (i = j = k = 0; i < (paylen / 16); i++) {
- if ((k & 3) != 2 && ((i % 580) != 579)) {
- sb.buffer.buffer_val[j++] =
- audio_s2u(((((unsigned short *) payload)[i * 8]) +
- (((unsigned short *) payload)[i * 8 + 1])) / 2);
- }
- k = (k + 1) % 11;
- }
- sb.buffer.buffer_len = j;
- }
- break;
-
- default:
- /* Unknown compression type. */
- break;
- }
- bcopy(&sb, pkt, (int) (((sizeof sb - BUFL)) + sb.buffer.buffer_len));
- return TRUE;
- }
- return FALSE;
- }
- #endif
-